﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SSharp.Core.Evaluator;
using Environment = SSharp.Core.Evaluator.Environment;
using SSharp.Core.Builtins.Macros;
using SSharp.Core.DataTypes;
using SSharp.Core.Builtins.Functions;
using SSharp.Core.Properties;
using System.IO;

namespace SSharp.Core.Builtins {
	public static class InitialEnvironment {
		private static Dictionary<string, object> definitions = new Dictionary<string, object> {
			// macros and evaluator syntax
			{ "begin", new InvalidMacro("begin") },
			{ "lambda", new InvalidMacro("lambda") },
			{ "ƛ", new InvalidMacro("ƛ") },
			{ "define", new InvalidMacro("define") },
			{ "if", new InvalidMacro("if") },
			{ "quote", new InvalidMacro("quote") },
			{ "quasiquote", new InvalidMacro("quasiquote") },
			{ "cond", new Cond() },
			{ "load", new Load() },
			{ "load.net", new LoadDotNet() },
			{ "let", new Let() },

			// .net
			{ "new", new New() },
			
			// functions
			{ "+", PrimitiveMath.Plus },
			{ "-", PrimitiveMath.Minus },
			{ "*", PrimitiveMath.Times },
			{ "/", PrimitiveMath.Divide },
			{ "remainder", PrimitiveMath.Remainder },
			{ "<", PrimitiveMath.LessThan },
			{ "<=", PrimitiveMath.LessThanOrEqual },
			{ ">", PrimitiveMath.MoreThan },
			{ ">=", PrimitiveMath.MoreThanOrEqual },
			{ "=", PrimitiveMath.Equals },
			{ "eq?", PrimitiveMath.Eq },
			
			{ "cons", PrimitiveCons.Cons },
			{ "car", PrimitiveCons.Car },
			{ "cdr", PrimitiveCons.Cdr },

			{ "and", PrimitiveBoolean.And },
			{ "or", PrimitiveBoolean.Or },
			{ "not", PrimitiveBoolean.Not },

			{ "random", PrimitiveRandom.Random },

			{ "integer?", PrimitiveTypeChecks.IsInteger },
			{ "decimal?", PrimitiveTypeChecks.IsDecimal },
			{ "number?", PrimitiveTypeChecks.IsNumber },
			{ "string?", PrimitiveTypeChecks.IsString },
			{ "symbol?", PrimitiveTypeChecks.IsSymbol },
			{ "empty?", PrimitiveTypeChecks.IsEmpty },
			{ "pair?", PrimitiveTypeChecks.IsPair },
			{ "null?", PrimitiveTypeChecks.IsNull },

			{ "rename-lambda", PrimitiveProcedures.RenameProcedure },

			// constants
			{ "true", true },
			{ "#t", true },
			{ "false", false },
			{ "#f", false },
			{ "null", null },

			{ "pi", (decimal)Math.PI },
			{ "empty", List.EmptyList.Instance }
		};

		public static IEnvironment Environment;

		static InitialEnvironment() {
			Environment = new Environment().AddFrame(new Frame(definitions));

			// Eval.EvalExpression(Load.LoadFile(new MemoryStream(Resources.Builtins)), Environment);
		}
	}
}